<?php

require_once('WRedis.php');

class WebSocket
{

    const HOST = '0.0.0.0';

    const PORT = 9502;

    private $websocket;

    public function __construct()
    {

        $this->websocket = new Swoole\WebSocket\Server(self::HOST,self::PORT);
        
        $this->websocket->on('open',[$this,'onOpen']);
        
        $this->websocket->on('message',[$this,'onMessage']);

        $this->websocket->on('request',[$this,'onRequest']);

        $this->websocket->on('close',[$this,'onClose']);

        $this->websocket->set([
            'enable_static_handler' => true,
            'document_root' => '/home/wwwroot/test-swoole/public',
        ]);

        echo "Swoole启动...\n";

        $this->websocket->start();


    }

    public function onRequest($request,$response)
    {

        if ($request->server['path_info'] == '/favicon.ico' || $request->server['request_uri'] == '/favicon.ico') {
            $response->end();
            return;
        }

        if(isset($request->post['act'])){
            $act = $request->post['act'];
            if($act == 'login'){

                $nickname = $request->post['nickname'];
                $avatar = $request->post['avatar'];
                $token = md5($nickname);
                $data = [
                    'token' => md5($nickname),
                    'nickname' => $nickname,
                    'avatar' => $avatar,
                ];
                // 更新用户信息
                \WRedis::getInstance()->set('users'.$token,$data);
                $response->end(json_encode($data));
    
            }elseif($act == 'upload'){
    
                $file = $request->files['file'];
                $fileName = md5(time().$file['name']).'.'.explode('/',$file['type'])[1];
                $filePath = __DIR__.'/../public/upload/'.$fileName;
                move_uploaded_file($file['tmp_name'],$filePath);
                $data = [
                    'image' => 'upload/'.$fileName,
                ];
                $response->end(json_encode($data));
    
            }elseif($act == 'logout'){
                $token = $request->post['token'];
                $userInfo = \WRedis::getInstance()->get('users'.$token);
                \WRedis::getInstance()->del('online_user'.$userInfo['fd']);
                \WRedis::getInstance()->del('users'.$token);
                $data = [
                    'status' => 1,
                ];
                $response->end(json_encode($data));
            }
        }

    }

    public function onOpen($server,$request)
    {

        if(!isset($request->cookie['token'])){
            $data = [
                'status' => 0,
            ];
            $server->push($request->fd,json_encode($data));
        }

        $token = $request->cookie['token'];
        $userData = \WRedis::getInstance()->get('users'.$token);

        // 判断是否存在
        if(!$userData){
            $data = [
                'status' => 0,
            ];
            $server->push($request->fd,json_encode($data));
        }else{
            $data = [
                'nickname' => $userData['nickname'],
                'avatar' => $userData['avatar'],
                'status' => 1,
                'type' => 3,
            ];
    
            // 绑定fd
            $userData['fd'] = $request->fd;
            \WRedis::getInstance()->set('users'.$token,$userData);
    
            // 写入列表
            \WRedis::getInstance()->setnx('online_user'.$request->fd,json_encode($userData));
    
            // 读取在线用户
            $data['online_users'] = $this->getUserList();
    
            foreach ($server->connections as $fd) {
                if ($server->isEstablished($fd)) {
                    $server->push($fd,json_encode($data));
                }
            }
        }
    }

    public function onMessage($server,$frame)
    {

        $wsData = json_decode($frame->data,1);
        if(isset($wsData['token'])){
            $userData = \WRedis::getInstance()->get('users'.$wsData['token']);
        }

        $data = [
            'avatar' => isset($userData['avatar'])?$userData['avatar']:rand(1000,10000),
            'nickname' => isset($userData['nickname'])?$userData['nickname']:rand(1000,10000),
            'message' => $wsData['message'],
            'time' => date('Y-m-d H:i:s',time()),
            'status' => 1,
            'fd' => $frame->fd,
            'token' => $wsData['token'],
        ];

        // 判断用户或群聊
        if($wsData['send_token']){
            
            $sendUserData = \WRedis::getInstance()->get('users'.$wsData['send_token']);
            $data['type'] = 2;
            echo '发送给:'.$sendUserData['nickname'].PHP_EOL;
            $server->push($sendUserData['fd'],json_encode($data));
            

        }else{
            $data['type'] = 5;
            foreach ($server->connections as $fd) {
                // 需要先判断是否是正确的websocket连接，否则有可能会push失败
                if ($server->isEstablished($fd) && $fd != $frame->fd) {
                    $server->push($fd,json_encode($data));
                }
            }
        }
    }

    public function onClose($server,$fd)
    {
        // 用户下线
        echo $fd.'下线'.PHP_EOL;
        \WRedis::getInstance()->del('online_user'.$fd);
        // 更新用户列表
        $data = [
            'status' => 2,
            'type' => 3,
        ];
        $data['online_users'] = $this->getUserList();
        $this->updateUserData($server,$data);
    }


    // 获取用户列表
    public function getUserList()
    {
        // 读取在线用户
        $onLineUsers = [];
        foreach(\WRedis::getInstance()->keys('online_user*') as $user){
            $onLineUsers[] = \WRedis::getInstance()->get($user);
        }
        return $onLineUsers;
    }

    // 更新所有用户数据
    public function updateUserData($server,$data)
    {
        $onLineUsers = $this->getUserList();
        foreach ($onLineUsers as $user) {
            $userInfo = json_decode($user,1);
            $server->push($userInfo['fd'],json_encode($data));
        }
    }

}

new WebSocket();